package p2p;

import java.net.DatagramPacket;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.StringTokenizer;

/** Class that will contain information about the last search and discovered files.
 * @author Bruno
 */
public class SearchList {

	static void startSearch(String filter) {
		// Create message
		String id = Global.generateSearchID();
		lastSearchID = id;
		
		// check the keywords (remove extra spaces)
		StringTokenizer tok = new StringTokenizer(filter);
		if(!tok.hasMoreTokens()) // no keywords specified
			return;
		filter = tok.nextToken();
		while(tok.hasMoreTokens()) 
			filter += " " + tok.nextToken();

		String message = "SEARCH " + id + " " + filter;

		// Clear frmP2P graphical table and "list"
		list.clear();
		if(Global.frmP2P != null)
			Global.frmP2P.SearchTable.setRowCount(0);


		// Create packet and send message to network
		DatagramPacket packet = new DatagramPacket(message.getBytes(), message.length(), Global.multicastInetAddr, Global.controlPort);
		try {
			Global.controlSocket.send(packet);
		} catch (Exception ex) {
			System.err.println("Error sending SEARCH command: " + ex.getMessage());
		}
	}

	/** Returns the ID of the last search.
	 * @return Last search ID.
	 */
	static String getLastSearchID() {
		return lastSearchID;
	}

	/** Returns the number of files in the list.
	 * @return Number of files in the list.
	 */
	static int getNumFiles() {
		return list.size();
	}

	/** Processes a received FOUND message.
	 * @param msg The message.
	 */
	static void processFoundMessage(String msg) {
		StringTokenizer tok = new StringTokenizer(msg);
		tok.nextToken(); // FOUND text

		if(tok.hasMoreTokens()) { // search-id
			String id = tok.nextToken();
			if(id.equals(getLastSearchID()) && tok.hasMoreTokens()) { // answer to a SEARCH message sent by this process
				String hash = tok.nextToken(); // sha (hash value)

				if(tok.hasMoreTokens()) { // size
					long size;
					try {
						size = Long.parseLong(tok.nextToken());
					}
					catch(NumberFormatException ex) {
						return; // size was not a valid number
					}

					if(tok.hasMoreTokens()) { // file name
						String name = tok.nextToken();
						while(tok.hasMoreTokens())
							name += " " + tok.nextToken();

						addFile(hash, name, size);
					}
				}
			}
		}
	}

	static private void addFile(String hash, String name, long size) {
		int index = searchHash(hash);

		if(index == -1) { // New file doesn't exist in the list: add it
			SearchFile file = new SearchFile(hash, name, size);
			file.addPeer();
			list.add(file);

			// update graphical table
			Object[] values = {name, file.getHumanReadableSize(), 1};
			Global.frmP2P.SearchTable.addRow(values);
		}
		else { // File exists: update number of peers
			SearchFile file = list.get(index);
			file.addPeer();
			Global.frmP2P.SearchTable.setValueAt(file.getPeers(), index, 2);
		}
	}

	/** Returns the index of the file with the indicated hash value on the list.<br>
	 * -1 is returned if the hash value is not found.
	 * @param hash Hash value to search.
	 * @return Index of file on the list.
	 */
	static int searchHash(String hash) {
		return list.indexOf(new SearchFile(hash, "", 0));
	}

	/** Returns the file with the indicated <i>index</i> from the list.
	 * @param index Index of the file in the list.
	 * @return Selected file (or null if invalid index).
	 */
	static SearchFile getFile(int index) {
		if(index < 0 || index >= list.size())
			return null;
		else
			return list.get(index);
	}

	private static String lastSearchID = null;
	private static List<SearchFile> list = new LinkedList<SearchFile>();
}
